#!/usr/bin/python
# -*- coding: UTF8 -*-
import os
import pynotify
import sys
import threading
from threading import Thread
import gtk
import gobject
import pygtk

import time 
import gettext
import locale
import md5
import sqlite3
import math

import sys
import urllib2
import urllib
from BeautifulSoup import BeautifulSoup



#encoding = locale.getpreferredencoding()
#print locale.getdefaultlocale()
#utf8conv = lambda x : unicode(x, encoding).encode('utf8')
gobject.threads_init()
gtk.gdk.threads_init()

class Falador():
    def __init__(self):
        self.contador = 0
        
        
    def Fale(self,texto,destino):
        
        if texto:
            partes = texto.split(". ")
            for txt in partes:
                open('/tmp/trans.spk','w').write(txt)
                print txt
                #Seguindo a sugestão do manual do espeak
                cmd = ['espeak','-p',str(app.pitch),'-a',str(app.amplitude),'-s',str(app.velocidade),'-v',app.vozes[destino],'-f','/tmp/trans.spk']
                try:
                    if pynotify.init("Markup"):
                        n = pynotify.Notification(u'SpeakTranslater Say:',txt)
                        n.set_urgency(pynotify.URGENCY_CRITICAL)
                        n.set_timeout(5000)
                        #n.set_hint("x", 150)
                        #n.set_hint("y", 10)

                        if not n.show():
                            print "Failed to send notification"
                        
                        
                    os.popen2(cmd)
                except:
                    print sys.exc_info()
        

class Tradutor(threading.Thread,Falador):
    def __init__(self):
        super(Tradutor, self).__init__()
        self.canal = urllib2.build_opener()
        self.canal.addheaders = [('User-agent','EspeakTranslater  0.0.1')]
        
        self.quit = False
        self.last_ident = md5.new("Start").hexdigest()
        self.traduzir = True
        self.falar = True
        
        
        
    def SetTraduzir(self,valor):
        self.traduzir = valor

    def SetFalar(self,valor):
        self.falar = valor
    
    def Traduz(self):
        
        try:
            texto = os.popen('xsel').read().strip()
        except:
           print sys.exc_info()
        else:
            if texto:
                
                ident = md5.new(texto.strip().lower()).hexdigest()
                
                if ident != self.last_ident:
                    self.last_ident = ident
                    sl = app.origem
                    destino = tl = app.destino
                    
                    traduzido = texto
                    
                    #Se WorkOffline Marcado como False,Traduzir
                    #pesquisar se ident existe:
                    con = app.SqlConn()
                    c = con.cursor()
                    q = (ident,tl,sl)
                    r = c.execute('select * from textos where ident=? and destino=? and origem=?', q)
                    linha = r.fetchone()
                    
                    #traduzir é uma variavel alterada pelo WorkOffline
                    if not app.traduzir:
                        resultado = None
                        if not linha:
                            volta = 0
                            #Tenta traduzir por 3 vezes...
                            # O google eventualmente retorna None
                            while not resultado:
                                if volta < 3:
                                    
                                    try:
                                        self.translated_page = self.canal.open("http://translate.google.com/translate_t?"+urllib.urlencode({'sl': sl, 'tl': tl}),
                                        data=urllib.urlencode({'hl': 'en','ie': 'UTF8','text': texto,'sl': sl, 'tl': tl}))
                                        translated_soup = BeautifulSoup(self.translated_page)
                                        resultado = traduzido = translated_soup('div', id='result_box')[0].string
                                        status = 1
                                    except:
                                        print sys.exc_info()
                                        volta +=3
                                        #No obteve a traducao, falar na origem
                                        destino = app.origem
                                        resultado = texto
                                        status = 0
                                    
                                else:
                                    destino = app.origem
                                    status = 0
                                volta += 1
                            if status:
                                try:
                                    ins = c.execute('insert into textos (ident,origem,destino,original,trans,status) values(\'%s\',\'%s\',\'%s\',\'%s\',\'%s\',\'%d\')' % (ident,app.origem,app.destino,texto,traduzido,status))
                                    con.commit()
                                except:
                                    print sys.exc_info()
                                    
                        
                        
                        
                        
                        else:
                            traduzido = linha[5]
                            

                            
                        
                        
                    else:
                        if not linha:
                            #Ok, o texto nao esta traduzido e estamos offline, falar o idioma original
                            destino = app.origem
                        else:
                            traduzido = linha[5]
                            
                    
                    con.close()
                        
                    if app.falar:
                        if texto:
                            self.Fale(traduzido,destino)
                
                



        
        
    def run(self):
        counter = 0
        while not self.quit:
            counter += 1
            gobject.idle_add(self.Traduz)
            time.sleep(0.5)


class SpeakTranslater():
    
    def __init__(self):
        os.popen('xsel --clear')
        gettext.bindtextdomain('MoTranslater', '/usr/local/share/motranslater/i18n/')
        gettext.textdomain('MoTranslater')
        self._ = gettext.gettext
        self.g = {u'el': u'Greek', u'en': u'English', u'vi': u'Vietnamese', u'ca': u'Catalan', u'it': u'Italian', u'iw': u'Hebrew', u'ar': u'Arabic', u'cs': u'Czech', u'et': u'Estonian', u'gl': u'Galician', u'id': u'Indonesian', u'es': u'Spanish', u'ru': u'Russian', u'nl': u'Dutch', u'pt': u'Portuguese', u'mt': u'Maltese', u'tr': u'Turkish', u'lt': u'Lithuanian', u'lv': u'Latvian', u'tl': u'Filipino', u'th': u'Thai', u'ro': u'Romanian', u'pl': u'Polish', u'fr': u'French', u'bg': u'Bulgarian', u'sl': u'Slovenian', u'hr': u'Croatian', u'de': u'German', u'hu': u'Hungarian', u'hi': u'Hindi', u'fi': u'Finnish', u'da': u'Danish', u'ja': u'Japanese', u'zh-TW': u'Chinese (Traditional)', u'sq': u'Albanian', u'no': u'Norwegian', u'ko': u'Korean', u'sv': u'Swedish', u'sk': u'Slovak', u'zh-CN': u'Chinese (Simplified)', u'uk': u'Ukrainian', u'sr': u'Serbian'}
        self.vozes = {'el': 'greek', 'en': 'default', 'vi': 'vietnam-test', 'it': 'italian', 'cs': 'czech', 'id': 'indonesian-test', 'es': 'spanish', 'ru': 'russian_test', 'nl': 'dutch-test', 'pt': 'brazil', 'no': 'norwegian-test', 'tr': 'turkish', 'ro': 'romanian', 'pl': 'polish', 'fr': 'french', 'hr': 'croatian', 'de': 'german', 'hu': 'hungarian', 'hi': 'hindi-test', 'fi': 'finnish', 'sr': 'serbian', 'sv': 'swedish', 'sk': 'slovak'}
        self.id_origem = ['cs', 'de', 'el', 'en', 'es', 'fi', 'fr', 'hi', 'hr', 'hu', 'id', 'it', 'nl', 'no', 'pl', 'pt', 'ro', 'ru', 'sk', 'sr', 'sv', 'tr', 'vi']
        
        self.database = "/home/lauro/motranslater.sqlite"
        self.execute = True
        con = self.SqlConn()
        c = con.cursor()
        r = c.execute('select * from config')
        
        #Corrigir para usar FetchOne
        if r:
            for config in r:
                self.origem,self.destino,self.falar,self.traduzir,self.amplitude,self.pitch,self.velocidade,self.welcome,self.servidor,self.email,self.senha = config
            #Uso futuro    
            if not self.servidor:
                self.servidor = "https://192.168.221.1:8778"
            if not self.email:
                self.email = "moblin@gurulinux.blog.br"
            if not self.senha:
                self.senha = "moblinuser"
        else:
            self.origem = 'en'
            self.destino = 'pt'
            self.falar = True
            self.traduzir = True
            self.amplitude = 10
            self.pitch = 30
            self.velocidade = 190 
            self.welcome = True
            self.servidor = "https://192.168.221.1:8778"
            self.email = "moblin@gurulinux.blog.br"
            self.senha = "moblinuser"
        
        con.close()    
        

        
        
        
       
        
        

        self.window = gtk.Window()
        self.window.resize(750,450)

        self.box1 = gtk.VBox()
        self.window.add(self.box1)
        self.box1.show()
        self.box2 = gtk.VBox(spacing=10)
        self.box2.set_border_width(10)
        self.box1.pack_start(self.box2)
        self.box2.show()

        self.notebook = gtk.Notebook()
        self.notebook.set_tab_pos(gtk.POS_TOP)
        self.box2.pack_start(self.notebook)
        self.notebook.show()

        #DashBoard
        self.names = [self._('SpeakTranslater DashBoard'), self._('Setup')]
        

             
        
        self.dashboard = gtk.HBox(False, 0)
        self.dashboard.set_border_width(10)



        #Options
        self.notedash = gtk.Notebook()
        self.notedash.set_tab_pos(gtk.POS_TOP)
        self.label = gtk.Label(self._(u'Options'))
        
        self.note_setup = gtk.ScrolledWindow()
        
        self.note_setup.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        

        #Setup
        self.setup = gtk.Frame(None)
        self.setup.set_border_width(1)
        
        
        
        #quadro para escolher origem e destino
        self.box_options = gtk.HBox(False,0)
        self.box_options.set_border_width(5)
        self.l_origem = gtk.Label(self._(u'From: ')) 
        self.box_options.pack_start(self.l_origem,False,False)
        self.combo_box_origem = gtk.combo_box_new_text()
        
        
  
        
        self.box_options.pack_start(self.combo_box_origem,False,False,5)


        
        
        self.l_destino = gtk.Label(self._(u'To')) 
        self.box_options.pack_start(self.l_destino,False,False,5)
        

        
        self.combo_box_destino = gtk.combo_box_new_text()
        
        
            
       

        
        self.box_options.pack_start(self.combo_box_destino,False,False,5)
        self.Falar = gtk.CheckButton(self._(u'Speak'))
        self.box_options.pack_start(self.Falar, False, False, 5)
        if self.falar:
            self.Falar.set_active(True)
        
        self.Falar.connect('toggled', self.On_Falar)
        
        self.offlinework = gtk.CheckButton(self._(u'Work Offline'))
        self.box_options.pack_start(self.offlinework, False, False, 5)
        if self.traduzir:
            self.offlinework.set_active(True)
            
        self.offlinework.connect('toggled', self.On_WorkOffline)
        
        self.salvar = gtk.Button(self._(u' Save Options '))
        self.salvar.connect("clicked", self.Salva_config)
        self.box_options.pack_end(self.salvar,False,False)
        #quadro para medidas
        self.all_box = gtk.VBox(False,1)


        #amplitude
        self.amp = gtk.Table(2, 2, False)
        self.amp.set_border_width(5)
        self.amp.set_row_spacings(5)
        self.amp.set_col_spacings(10)
        
        
        self.amp_label = gtk.Label(self._(u'Amp:'))
        self.amp_label.set_use_underline(True)
        self.amp_label.set_alignment(0, 1)
        

        self.amp_adj1 = gtk.Adjustment(self.amplitude, 0, 21, 0, 1, 1)
        self.amp_vscale = gtk.HScale(self.amp_adj1)
        
        self.amp_adj1.connect("value_changed", self.update_amp)
        self.amp.attach(self.amp_label, 0, 1, 0, 0 + 1, 0, 0, 0, 0)
        self.amp_vscale.show()
        self.amp.attach(self.amp_vscale,  1, 2, 0, 0 + 1, gtk.EXPAND | gtk.FILL, 0, 0, 0)    
        
        

        #Pitch
        self.p = gtk.Table(2, 2, False)
        self.p.set_border_width(5)
        self.p.set_row_spacings(5)
        self.p.set_col_spacings(10)
        
        
        self.p_label = gtk.Label(self._(u'Pitch:'))
        self.p_label.set_use_underline(True)
        self.p_label.set_alignment(0, 1)
        

        self.p_adj1 = gtk.Adjustment(self.pitch, 0, 100, 0, 1, 1)
        self.p_vscale = gtk.HScale(self.p_adj1)
        
        self.p_adj1.connect("value_changed", self.update_pitch)
        self.p.attach(self.p_label, 0, 1, 0, 0 + 1, 0, 0, 0, 0)
        self.p_vscale.show()
        self.p.attach(self.p_vscale,  1, 2, 0, 0 + 1, gtk.EXPAND | gtk.FILL, 0, 0, 0)    
        
        
        
        #Velocidade
        self.velo = gtk.Table(2, 2, False)
        self.velo.set_border_width(5)
        self.velo.set_row_spacings(5)
        self.velo.set_col_spacings(10)
        
        
        self.velo_label = gtk.Label(self._(u'Words per minute:'))
        self.velo_label.set_use_underline(True)
        self.velo_label.set_alignment(0, 1)
        

        self.velo_adj1 = gtk.Adjustment(self.velocidade, 50, 301, 0, 1, 1)
        self.velo_vscale = gtk.HScale(self.velo_adj1)
        
        self.velo_adj1.connect("value_changed", self.update_velo)
        self.velo.attach(self.velo_label, 0, 1, 0, 0 + 1, 0, 0, 0, 0)
        self.velo_vscale.show()
        self.velo.attach(self.velo_vscale,  1, 2, 0, 0 + 1, gtk.EXPAND | gtk.FILL, 0, 0, 0)
        
        
        self.teste = gtk.HBox(False,5)
        self.teste.set_border_width(5)
        self.teste_label = gtk.Label(self._(u'Text:'))
        self.teste_entry = gtk.Entry()
        
        self.combo_teste_destino = gtk.combo_box_new_text()
        
        for i in self.id_origem:
            self.combo_box_origem.append_text('%s' % self.g[i])
            self.combo_box_destino.append_text('%s' % self.g[i])  
            self.combo_teste_destino.append_text('%s' % self.g[i])  
            
        self.combo_box_origem.set_active(self.id_origem.index(self.origem))
        self.combo_box_destino.set_active(self.id_origem.index(self.destino))
        self.combo_teste_destino.set_active(self.id_origem.index(self.destino))
        
        self.teste_botao = gtk.Button(self._(u' Test Speak '))
        self.teste_botao.connect("clicked", self.Speak)
        
        
   
       
       
        

        
     
        
        
        
        self.teste.pack_start(self.teste_label,False,False,2)
        self.teste.pack_start(self.teste_entry,True,True,2)
        #self.teste.pack_start(self.combo_teste_destino,False,False,2)
        
        
        self.teste.pack_start(self.teste_botao,False,False,12)
        
        self.all_box.pack_start(self.box_options,False,False,5)
        self.all_box.pack_start(self.amp,False,False,5)
        self.all_box.pack_start(self.p,False,False,5)
        self.all_box.pack_start(self.velo,False,False,5)
        self.all_box.pack_start(self.teste,False,False,5)
       
     
        
        self.setup.add(self.all_box)    
        self.setup.show()
        
        
        
        
        self.note_setup.add_with_viewport(self.setup)
        
        self.notedash.append_page(self.note_setup,self.label)
        self.dashboard.pack_end(self.notedash,True,True,1)
        self.notedash.show()
        
        
        self.label = gtk.Label(self.names[0])
        self.notebook.append_page(self.dashboard,self.label)         

        
        

        
        
        #self.add_window(self.window)
        
        
        self.window.set_title(self._('SpeakTranslater'))
        self.window.connect("destroy", gtk.main_quit)


        
        self.window.show_all()
        self.notebook.set_current_page(0)
    
    

        
        

        
    
    
    
                    
                    
    def Salva_config(self,sinal):
        con = self.SqlConn()
        c = con.cursor()
        
        
        
        self.origem = [ key for key in self.g if self.g[key] == self.combo_box_origem.get_active_text()  ][0]
        self.destino = [ key for key in self.g if self.g[key] == self.combo_box_destino.get_active_text()  ][0]
        

        #FIX-ME
        #humm... sqlite nao tem bool? Tem sim, mas nao funcionou 
        # q gambiarra... Arrumar 
        
        if self.traduzir:
            traduz = 1
        else:
            traduz = 0
            
        if self.falar:
            falar = 1
        else:
            falar = 0
        
                
        c.execute('UPDATE config SET falar=%d,traduzir=%d,amplitude=%d,pitch=%d,velocidade=%d,origem=\'%s\',destino=\'%s\'' % (falar,traduz,self.amplitude,self.pitch,self.velocidade,self.origem,self.destino))
        con.commit()
        con.close()
        
        
    #FIX-ME: Aplicar DRY nessa zona...
    def Speak(self,sinal):
        destino = [ key for key in self.g if self.g[key] == self.combo_teste_destino.get_active_text()  ][0]
        texto = self.teste_entry.get_text()

        self.Fale(texto,self.destino)

    def update_amp(self,regua):
        self.amplitude = int(math.ceil(regua.value))
        
    def update_pitch(self,regua):
        
        self.pitch = int(math.ceil(regua.value))
        
    def update_velo(self,regua):
        self.velocidade = int(math.ceil(regua.value))
        

    def On_WorkOffline(self,botao):
        if botao.get_active():
            self.traduzir = True
        else:
            self.traduzir = False
        
        
        
    def On_Falar(self,botao):
        if botao.get_active():
            self.falar = True
        else:
            self.falar = False

        

    def Debug(self,msg):
        log = open('/tmp/debug_motranslater.log','w+')
        log.write(msg+'\n')
        log.close()

        
            
                
    def SqlConn(self):
        conn = sqlite3.connect(self.database)
        return conn
    
    def SqlClose(self,conn):
        if conn.close():
            return True
        
    



    def destroy(self,sinal):
        self.execute = False
        self.window.destroy()
        gtk.main_quit()


    def _add_menu(self):
        menu = gtk.Menu()
        sair = gtk.MenuItem(self._('Sair'))
        sair.connect("activate", self.destroy)
        
        sobre = gtk.MenuItem(self._('Sobre'))


        menu.add(sobre)
        menu.add(sair)
        
        self.set_common_menu(menu) 
   
    def run(self):
        t = Tradutor()
        t.start()
        t.SetTraduzir(self.traduzir)
        t.SetFalar(self.falar)
        gtk.main()
        t.quit = True
        

if __name__ == "__main__":
    app = SpeakTranslater()
    app.run()
    
       
